#Bet files format
#================
#For Lotto: One bet per line, no empty lines no spaces at the start and the end of the line. One space separatio. E.g:
#01 02 03 04 05 06
#
#For EuroMillons: One bet per line, no empty lines no spaces at the start and the end of the line. Lucky numbers will have a 'b' right before the number. E.g:
#01 02 03 04 05 b1 b2
#
#Help
#====
#python pylot.py -h
#Usage: pylot.py [options] combination bonus
#
#Options:
#  --version             show program's version number and exit
#  -h, --help            show this help message and exit
#  -i IFILE, --input=IFILE
#                        Input file, by default bets.txt. The expected file is
#                        a set lines with all the bets. Each line contains one
#                        bet and only numbers.
#  -o OFILE, --output=OFILE
#                        Output file. By default it is printed on screen
#  -v, --verbose         Activates debug output
#  -e, --euro            By default it checks Lotto lottery, use this option to
#                        check euromillons lottery
#                        
#Commands & output
#=================
#$$ python pylot.py "25 12 19 18 36 45" "24"
#
#25 39 38 17 44 34  Loser: 1 matches
#24 12 19 18 44 33  WINNER: 3 matches + bonus
#11 10 15 18 36 24  Loser: 2 matches
#03 07 19 45 36 29  WINNER: 3 matches
#20 19 18 31 42 37  Loser: 2 matches
#10 20 14 45 29 21  Loser: 1 matches
#13 27 05 18 26 40  Loser: 1 matches
#
#$$ python pylot.py -e -i euro.txt "17 10 14 18 15" "1 2"
#
#13 27 05 18 26 b4 b3  Loser: 1 matches
#03 07 19 36 29 b4 b5  Loser: 0 matches
#11 10 15 18 b7 24 b8  WINNER: 3 matches
#20 19 18 31 37 b1 b9  Loser: 1 matches + 1 lucky numbers
#10 20 14 29 b2 b3 21  WINNER: 2 matches + 1 lucky numbers
#25 39 38 17 34 b1 b2  WINNER: 1 matches + 2 lucky numbers
#24 12 b5 19 18 33 b6  Loser: 1 matches

from __future__ import print_function
from optparse import OptionParser
import sys

def main():
    #prepare parser
    optparser = OptionParser(usage="usage: %prog [options] combination bonus", version="%prog 1.0")
    optparser.add_option("-i", "--input", dest="ifile", default="lotto.txt", help="Input file, by default bets.txt. The expected file is a set lines with all the bets. Each line contains one bet and only numbers.")
    optparser.add_option("-o", "--output", dest="ofile", default="stdout", help="Output file. By default it is printed on screen")
    optparser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="Activates debug output")
    optparser.add_option("-e", "--euro", action="store_true", dest="euro", default=False, help="By default it checks Lotto lottery, use this option to check euromillons lottery")
    
    #parse option and arguments
    (options, args) = optparser.parse_args()
    
    #check number ofarguments
    if len(args) != 2:
        optparser.error("Incorrect number of arguments. Winner combination and bonus expected")
    
    #VERBOSE
    pDebug(options, "Winner combination " + args[0])

    #check it is just numbers and spaces
    if not (args[0].replace(" ", "").isdigit() and args[1].replace(" ", "").isdigit()) :
        pErrorExit("Winner combination and bonus must be only numbers and spaces. Value= " + args[0] + " / " + args[1])
    
    #store in a set the winner combination  
    if options.euro:
        winnerbet = loadWinnerBetEuro(args[0])
    else:
        winnerbet = loadWinnerBetLotto(args[0])
    
    #VERBOSE
    pDebugBetSet(options, winnerbet, "Winner bet")
    
    #store in a set the extra numbers
    if options.euro:
        winnerbonus = loadWinnerBonusEuro(args[1])
    else:
        winnerbonus = loadWinnerBonusLotto(args[1])
            
    #VERBOSE
    pDebugBetSet(options, winnerbonus, "Winner bonus")
    
    #store all the bets in the file in a sets
    allbets = loadAllBets(options.ifile)
    
    #VERBOSE        
    if options.verbose:
        pDebug(options, "All bets")
        for onebet in allbets:
            pBetSetSorted(onebet)
    
    #match bets and winner
    if options.euro:
        matchEuro(winnerbet, winnerbonus, allbets)
    else:
        matchLotto(winnerbet, winnerbonus, allbets)
                
        
########## Subroutines ############   
def pErrorExit(msg):
    print("ERROR: " + msg);
    sys.exit()

def pDebug(options, msg):
    if options.verbose:
        print("DEBUG: " + msg)
        
def pBetSet(betset, ending="\n"):
    for num in betset: 
        print(num, end=" ")
    print(ending, end="")

def pBetSetsorted(betset, ending="\n"):
    #create a ordered list
    laux = sorted(betset)
    #laux.sort()
    for num in laux: 
        print(num, end=" ")
    print(ending, end="")

def pDebugBetSet(options, betset, msg):
    if options.verbose:
        print("DEBUG: " + msg)
        pBetSetSorted(betset)
   
def matchLotto(winnerbet, winnerbonus, allbets):
    for onebet in allbets:
        matches = len(winnerbet.intersection(onebet))
        bonuses = len(winnerbonus.intersection(onebet))
        pBetSetsorted(onebet, " ")
        if matches < 3:
            print("Loser:", matches, "matches")
        else:
            if bonuses == 1:
                print("WINNER:", matches, "matches + bonus")
            else:
                print("WINNER:", matches, "matches")
    
def matchEuro(winnerbet, winnerbonus, allbets):
    for onebet in allbets:
        matches = len(winnerbet.intersection(onebet))
        bonuses = len(winnerbonus.intersection(onebet))
        pBetSetsorted(onebet, " ")
        if  matches < 3 and not (matches == 1 and bonuses == 2) and not (matches == 2 and bonuses > 0):
            if bonuses > 0:
                print("Loser:", matches, "matches +", bonuses, "lucky numbers")
            else:
                print("Loser:", matches, "matches")
        else:
            if bonuses > 0:
                print("WINNER:", matches, "matches +", bonuses, "lucky numbers")
            else:
                print("WINNER:", matches, "matches")
        
def loadAllBets(file):
    allbets = set([])
    with open(file) as f:
        for line in f:
            allbets.add(frozenset(line.strip().split(" ")))
    return allbets

def loadWinnerBetLotto(winnerbet):
    winnerbetset = set(winnerbet.split(" "))
    if len(winnerbetset) != 6:
        pErrorExit("Lotto main winner combination musthave 6 numbers. Value= " + winnerbet)
    return winnerbetset

def loadWinnerBetEuro(winnerbet):
    winnerbetset = set(winnerbet.split(" "))
    if len(winnerbetset) != 5:
        pErrorExit("Euromillons main winner combination must have 5 numbers. Value= " + winnerbet)
    return winnerbetset

def loadWinnerBonusLotto(winnerbonus):
    winnerbonusset = set(winnerbonus.split(" "))
    if len(winnerbonusset) != 1:
        pErrorExit("Lotto must have 1 bonus number. Value= " + winnerbonus)
    return winnerbonusset
            
def loadWinnerBonusEuro(winnerbonus):            
    #need to add 'b' to lucky numbers to match them with the bets in the file
    winnerbonusset = set([])
    lucky = winnerbonus.split(" ")
    for num in lucky:
        winnerbonusset.add("b"+num)    
    if len(winnerbonusset) != 2:
        pErrorExit("Euromillons must have 2 lucky numbers. Value= " + winnerbonus)
    return winnerbonusset
        
    
if __name__ == "__main__":
    main()